import { ref } from "vue";

/**
 * WebSocket管理器类 - 提供WebSocket连接的管理、消息收发、心跳检测等功能
 *
 * @example
 * // 初始化WebSocket连接
 * const ws = useWebSocket('ws://example.com', {
 *   reconnectInterval: 5000,  // 自定义重连间隔
 *   heartbeatInterval: 20000   // 自定义心跳间隔
 * });
 *
 * // 订阅消息
 * const unsubscribe = ws.onMessage(data => {
 *   console.log('收到消息:', data);
 * });
 *
 * // 发送消息
 * ws.send({ type: 'chat', content: 'Hello!' });
 *
 * // 关闭连接
 * ws.close();
 * // 取消订阅
 * unsubscribe();
 */
// 192.168.5.39  ws://localhost:8080/api/zjjscApi/ws
class WebSocketManager {
  /**
   * 创建WebSocket管理器实例
   * @param {string} url - WebSocket服务器地址
   * @param {Object} options - 配置选项
   * @param {number} [options.reconnectInterval=3000] - 重连间隔时间(毫秒)
   * @param {number} [options.heartbeatInterval=30000] - 心跳间隔时间(毫秒)
   */
  constructor(url, options = {}) {
    this.url = url;
    this.options = {
      reconnectInterval: 300, // 重连间隔时间
      heartbeatInterval: 3000, // 心跳间隔时间
      ...options,
    };
    this.ws = null;
    this.isConnected = ref(false);
    this.reconnectTimer = null; // 重连定时器
    this.heartbeatTimer = null; // 心跳定时器
    this.messageCallbacks = new Set(); // 消息回调集合
    this.init(); // 初始化连接
  }

  init() {
    this.connect(); // 初始化连接
  }

  connect() {
    try {
      this.ws = new WebSocket(this.url);
      this.bindEvents();
    } catch (error) {
      console.error("WebSocket连接失败:", error);
      this.reconnect();
    }
  }

  // 绑定WebSocket事件
  bindEvents() {
    this.ws.onopen = () => {
      console.log("WebSocket连接成功");
      this.isConnected.value = true;
      this.startHeartbeat();
      if (this.reconnectTimer) {
        clearTimeout(this.reconnectTimer);
        this.reconnectTimer = null;
      }
    };

    this.ws.onclose = () => {
      console.log("WebSocket连接关闭");
      this.isConnected.value = false;
      this.stopHeartbeat();
      this.reconnect();
    };

    this.ws.onerror = (error) => {
      console.error("WebSocket错误:", error);
      this.isConnected.value = false;
    };

    this.ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        // console.log("收到消息:", data);

        // 处理心跳响应

        // 触发消息回调
        this.messageCallbacks.forEach((callback) => callback(data));
      } catch (error) {
        console.error("消息处理错误:", error);
      }
    };
  }

  reconnect() {
    if (this.reconnectTimer) return;

    this.reconnectTimer = setTimeout(() => {
      console.log("尝试重新连接...");
      this.connect();
    }, this.options.reconnectInterval);
  }
  // 心跳检测
  startHeartbeat() {
    if (this.heartbeatTimer) return;

    this.heartbeatTimer = setInterval(() => {
      if (this.isConnected.value) {
        this.send({ type: "heartbeat" });
      }
    }, this.options.heartbeatInterval);
  }

  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  /**
   * 发送消息到WebSocket服务器
   * @param {Object} data - 要发送的消息数据，将被自动转换为JSON字符串
   */
  send(data) {
    if (!this.isConnected.value) {
      console.warn("WebSocket未连接，消息发送失败");
      return;
    }
    try {
      this.ws.send(JSON.stringify(data));
    } catch (error) {
      console.error("消息发送失败:", error);
    }
  }

  /**
   * 订阅WebSocket消息
   * @param {Function} callback - 消息处理回调函数，接收解析后的消息数据作为参数
   * @returns {Function} 取消订阅的函数
   */
  onMessage(callback) {
    if (typeof callback === "function") {
      this.messageCallbacks.add(callback);
    }
    return () => this.messageCallbacks.delete(callback); // 返回取消订阅函数
  }

  /**
   * 关闭WebSocket连接，清理定时器和事件监听
   */
  close() {
    this.stopHeartbeat();
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
    if (this.ws) {
      this.ws.close();
    }
  }
}

// 创建单例实例
let wsInstance = null;

/**
 * 创建或获取WebSocket管理器实例（单例模式）
 * @param {string} url - WebSocket服务器地址
 * @param {Object} [options={}] - 配置选项，同WebSocketManager构造函数的options参数
 * @returns {WebSocketManager} WebSocket管理器实例
 */
export const useWebSocket = (url, options = {}) => {
  if (!wsInstance) {
    wsInstance = new WebSocketManager(url, options);
  }
  return wsInstance;
};
